package main

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	pb "github.com/hyperledger/fabric/protos/peer"
)

type MAChaincode struct {
}
type Files struct {
	FileName    string `json:"fileName"`
	FileAddress string `json:"fileAddress"`
}

type Obj struct {
	AppId    string  `json:"appId"`
	SystemId string  `json:"systemId"`
	Files    []Files `json:"files"`
}
//合同变量
type EvidenceData struct {
	RequestTime string `json:"RequestTime"`
	ContractName string `json:"ContractName"`
	ContractType string `json:"ContractType"`
	FactoringA string `json:"factoringA"`
	FactoringB string `json:"factoringB"`
	LegalA string `json:"legalA"`
	LegalB string `json:"legalB"`
	AddressA string `json:"addressA"`
	AddressB string `json:"addressB"`
	CeCodeA string `json:"ceCodeA"`
	CeCodeB string `json:"ceCodeB"`
	ContactA string `json:"contactA"`
	ContactB string `json:"contactB"`
	BasicServiceType string `json:"BasicServiceType"`
	ExpectedDate string `json:"ExpectedDate"`
	OtherAgreements string `json:"otherAgreements"`
	TransferAppNo string `json:"TransferAppNo"`
	ProductType string `json:"productType"`
	ProductName string `json:"productName"`
	Amount string `json:"amount"`
	Discountamount string `json:"discountamount"`
	Factoringfee string `json:"factoringfee"`
	Transactionconsideration string `json:"transactionconsideration"`
	Discountrate string `json:"discountrate"`
	Collectionnumber string `json:"collectionnumber"`
	Collectionname string `json:"collectionname"`
	Collectionopeningbankname string `json:"collectionopeningbankname"`
	Collectionlargenumber string `json:"collectionlargenumber"`
	Paymentnumber string `json:"paymentnumber"`
	Paymentname string `json:"paymentname"`
	Paymentopeningbankname string `json:"paymentopeningbankname"`
	Paymentlargenumber string `json:"paymentlargenumber"`
	Factoringaccount string `json:"factoringaccount"`
	Factoringaccountnumber string `json:"factoringaccountnumber"`
	Factoringaccountname string `json:"factoringaccountname"`
	Factoringaccountbankname string `json:"factoringaccountbankname"`
	Factoringaccountlargenumber string `json:"factoringaccountlargenumber"`
	SigningdateA string `json:"signingdateA"`
	SigningB string `json:"signingB"`
	Attachmenthash string `json:"attachmenthash"`
	Files        []Files `json:"files"`
	MaxchainHash string  `json:"maxchainHash"`
}

type Evidence struct {
	AppId        string       `json:"appId"`
	SystemId     string       `json:"systemId"`
	ContractNo string 		  `json:"contractNo"`
	EvidenceData EvidenceData `json:"evidenceData"`
}
//正向保理实例化
//type ForwardFactorData struct {
//	ContractNo string `json:"ContractNo"`
//	RequestTime string `json:"RequestTime"`
//	ContractName string `json:"ContractName"`
//	ContractType string `json:"ContractType"`
//	FactoringA string `json:"factoringA"`
//	FactoringB string `json:"factoringB"`
//	LegalA string `json:"legalA"`
//	LegalB string `json:"legalB"`
//	AddressA string `json:"addressA"`
//	AddressB string `json:"addressB"`
//	CeCodeA string `json:"ceCodeA"`
//	CeCodeB string `json:"ceCodeB"`
//	ContactA string `json:"contactA"`
//	ContactB string `json:"contactB"`
//	BasicServiceType string `json:"BasicServiceType"`
//	ExpectedDate string `json:"ExpectedDate"`
//	OtherAgreements string `json:"otherAgreements"`
//	TransferAppNo string `json:"TransferAppNo"`
//	ProductType string `json:"productType"`
//	ProductName string `json:"productName"`
//	Amount string `json:"amount"`
//	Discountamount string `json:"discountamount"`
//	Factoringfee string `json:"factoringfee"`
//	Transactionconsideration string `json:"transactionconsideration"`
//	Discountrate string `json:"discountrate"`
//	Collectionnumber string `json:"collectionnumber"`
//	Collectionname string `json:"collectionname"`
//	Collectionopeningbankname string `json:"collectionopeningbankname"`
//	Collectionlargenumber string `json:"collectionlargenumber"`
//	Paymentnumber string `json:"paymentnumber"`
//	Paymentname string `json:"paymentname"`
//	Paymentopeningbankname string `json:"paymentopeningbankname"`
//	Paymentlargenumber string `json:"paymentlargenumber"`
//	Factoringaccount string `json:"factoringaccount"`
//	Factoringaccountnumber string `json:"factoringaccountnumber"`
//	Factoringaccountname string `json:"factoringaccountname"`
//	Factoringaccountbankname string `json:"factoringaccountbankname"`
//	Factoringaccountlargenumber string `json:"factoringaccountlargenumber"`
//	SigningdateA string `json:"signingdateA"`
//	SigningB string `json:"signingB"`
//	Attachmenthash string `json:"attachmenthash"`
//}
//星券协议变量
type StarContract struct {
	RequesTime   string `json:"requesTime"`
	ContractName  string `json:"contractName"`
	ContractType  string `json:"contractType"`
	FactoringApplicant string `json:"factoringApplicant"`
	Factor   string `json:"factor"`
	LegalA   string `json:"legalA"`
	LegalB   string `json:"legalB"`
	AddressA string `json:"addressA"`
	AddressB string `json:"addressB"`
	SocialCreditCodeA string `json:"socialCreditCodeA"`
	SocialCreditCodeB string `json:"socialCreditCodeB"`
	ContactA string `json:"contactA"`
	ContactB string `json:"contactB"`
	ReceivableAmount  string `json:"receivableAmount"`
	ComprehensiveDiscountRate string `json:"comprehensiveDiscountRate"`
	TransactionConsideration  string `json:"transactionConsideration"`
	ExpectedTransferDate  string `json:"expectedTransferDate"`
	CollectionAccount string `json:"collectionAccount"`
	CollectionAccountName string `json:"collectionAccountName"`
	CollectionBankName string `json:"collectionBankName"`
	CollectionBankNum string `json:"collectionBankNum"`
	PaymentAccount    string `json:"paymentAccount"`
	PaymentAccountName string `json:"paymentAccountName"`
	PaymentBankName string `json:"paymentBankName"`
	PaymentBankNum string `json:"paymentBankNum"`
	TransferTimes  string `json:"transferTimes"`
	SignDate string `json:"signDate"`
	AttachmentHash string `json:"attachmentHash"`
	Files        []Files `json:"files"`
	MaxchainHash string  `json:"maxchainHash"`
}

type EvidenceXQ struct {
	AppId        string       `json:"appId"`
	SystemId     string       `json:"systemId"`
	ContractNum  string 	  `json:"contractNum"`
	StarContract StarContract `json:"starContract"`
}

func (t *MAChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
	//args:= stub.GetStringArgs()
	//
	//err := stub.PutState(args[1],[]byte(args[1]))
	//
	//if err != nil {
	//	shim.Error(err.Error())
	//}
	return shim.Success(nil)
}

func (t *MAChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
	function, args := stub.GetFunctionAndParameters()

	if function == "contractCreate" {
		return t.init(stub, args)
	}
	if function == "contractUpdate" {
		return t.contractUpdate(stub, args)
	}
	if function == "contractQuery" {
		return t.query(stub, args)
	}
	if function == "delete" {
		return t.delete(stub, args)
	}
	if function == "agreementCreate" {
		return t.initAgreement(stub, args)
	}
	if function == "agreementUpdate" {
		return t.agreementUpdate(stub, args)
	}
	if function == "agreementQuery" {
		return t.queryAgreement(stub, args)
	}
	return shim.Error(fmt.Sprintf("unknown function %s", function))
}

func checkParams(args []string, length int, number int) string {
	var res string
	if len(args) != length {
		res = fmt.Sprintf("invalid number of args %d", len(args))
		fmt.Println(res)
	} else {
		for i := 0; i < number; i++ {
			if len(args[i]) <= 0 {
				res = fmt.Sprintf("%dst argument must be a non-empty string", (i + 1))
				break
			}
		}
	}
	return res
}
//将字符串数组类型转换成结构体实例化
//func contractArgs(args []string)(*ForwardFactorData,error){
//	if len(args)!=41{
//		return nil, errors.New("Incorrect number of arguments. ")
//	}
//	contractNum :=args[0]
//	requesTime :=args[1]
//	contractName :=args[2]
//	contractType :=args[3]
//	factoringApplicant :=args[4]
//	factor :=args[5]
//	legalA :=args[6]
//	legalB :=args[7]
//	addressA :=args[8]
//	addressB :=args[9]
//	socialCreditCodeA :=args[10]
//	socialCreditCodeB :=args[11]
//	contactA :=args[12]
//	contactB :=args[13]
//	basicContractServiceType :=args[14]
//	expectedTransferDate :=args[15]
//	otherAgreement :=args[16]
//	transferApplicationNum :=args[17]
//	productType :=args[18]
//	productName :=args[19]
//	financeAmount :=args[20]
//	discountAmount :=args[21]
//	factoringFee :=args[22]
//	transactionConsideration :=args[23]
//	discountRate :=args[24]
//	collectionAccount :=args[25]
//	collectionAccountName :=args[26]
//	collectionBankName :=args[27]
//	collectionBankNum :=args[28]
//	paymentAccount :=args[29]
//	paymentAccountName :=args[30]
//	paymentBankName :=args[31]
//	paymentBankNum :=args[32]
//	factoringApplicantccount :=args[33]
//	factoringApplicantAccount :=args[34]
//	factoringApplicantAccountName :=args[34]
//	factoringApplicantBankName :=args[36]
//	factoringApplicantBankNum :=args[37]
//	contractSignDateA :=args[38]
//	contractSignDateB :=args[39]
//	attachmentHash :=args[40]
//	forwardFactorData := &ForwardFactorData{contractNum,requesTime,contractName,contractType,factoringApplicant,factor,legalA,legalB,addressB, socialCreditCodeA,socialCreditCodeB,contactA,contactB,addressA,basicContractServiceType,expectedTransferDate,otherAgreement,transferApplicationNum,productType,productName, financeAmount,discountAmount,factoringFee,transactionConsideration,discountRate,collectionAccount,collectionAccountName,collectionBankName, collectionBankNum,paymentAccount,paymentAccountName,paymentBankName,paymentBankNum, factoringApplicantccount,factoringApplicantAccount,factoringApplicantAccountName,factoringApplicantBankName,factoringApplicantBankNum,contractSignDateA,contractSignDateB,attachmentHash}
//	return forwardFactorData,nil
//}

//合同正向代理
func (t *MAChaincode) init(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	res := checkParams(args, 42, 42)
	if res != "" {
		return shim.Error(res)
	}
	fmt.Println("res==="+res)
	//// 将字符串数组类型数据转换为"员工"结构体
	//	//contractArgs, err := contractArgs(args)
	//	//if err != nil {
	//	//	return shim.Error(err.Error())
	//	//}
	//	//fmt.Println("contractArgs:", contractArgs)
	//	//ContractNo := contractArgs.ContractNo
	var obj Obj
	err := json.Unmarshal([]byte(args[0]), &obj)
	if err != nil {
		return shim.Error(err.Error())
	}
	fmt.Println("args[0]==="+args[0])
	//-------------------
	h := sha256.New()
	h.Write([]byte(args[0]+args[1]+args[2]+args[3]+args[4]+args[5]+args[6]+args[7]+args[8]+args[9]+args[10]+args[11]+args[12]+args[13]+args[14]+args[15]+args[16]+args[17]+args[18]+args[19]+args[20]+args[21]+args[22]+args[23]+args[24]+args[25]+args[26]+args[27]+args[28]+args[29]+args[30]+args[31]+args[32]+args[33]+args[34]+args[35]+args[36]+args[37]+args[38]+args[39]+args[40]+args[41]))
	sum := h.Sum(nil)
	maxchainHash := hex.EncodeToString(sum)
	evidenceData := &EvidenceData{args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28],args[29],args[30],args[31],args[32],args[33],args[34],args[35],args[36],args[37],args[38],args[39],args[40],args[41],obj.Files,maxchainHash}
	evidence := &Evidence{AppId: obj.AppId, SystemId: obj.SystemId,ContractNo:args[1]}
	evidence.EvidenceData = *evidenceData
	//-----------------
	evidences, err := stub.GetState(args[1])
	if err != nil {
		return shim.Error("Failed to get evidence: " + err.Error())
	} else if evidences != nil {
		fmt.Println("This evidence already exists")
		return shim.Error("This evidence already exists")
	}

	eviJSONasBytes, err := json.Marshal(evidence)
	if err != nil {
		return shim.Error(err.Error())
	}
	fmt.Println("key"+evidence.ContractNo)
	err = stub.PutState(args[1], eviJSONasBytes)
	if err != nil {
		return shim.Error(err.Error())
	}
	return shim.Success(nil)
}
//合同合约修改
func (t *MAChaincode) contractUpdate(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	res := checkParams(args, 42, 42)
	if res != "" {
		return shim.Error(res)
	}
	var obj Obj
	err := json.Unmarshal([]byte(args[0]), &obj)
	if err != nil {
		return shim.Error(err.Error())
	}
	h := sha256.New()
	h.Write([]byte(args[0]+args[1]+args[2]+args[3]+args[4]+args[5]+args[6]+args[7]+args[8]+args[9]+args[10]+args[11]+args[12]+args[13]+args[14]+args[15]+args[16]+args[17]+args[18]+args[19]+args[20]+args[21]+args[22]+args[23]+args[24]+args[25]+args[26]+args[27]+args[28]+args[29]+args[30]+args[31]+args[32]+args[33]+args[34]+args[35]+args[36]+args[37]+args[38]+args[39]+args[40]+args[41]))
	sum := h.Sum(nil)
	maxchainHash := hex.EncodeToString(sum)
	evidenceData := &EvidenceData{args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28],args[29],args[30],args[31],args[32],args[33],args[34],args[35],args[36],args[37],args[38],args[39],args[40],args[41],obj.Files,maxchainHash}
	evidence := &Evidence{AppId: obj.AppId, SystemId: obj.SystemId,ContractNo:args[1]}
	evidence.EvidenceData = *evidenceData
	evidences, err := stub.GetState(args[1])
	if err != nil {
		return shim.Error("Failed to get evidence: " + err.Error())
	} else if evidences == nil {
		fmt.Println("This evidence not exists")
		return shim.Error("This evidence not exists")
	}
	eviJSONasBytes, err := json.Marshal(evidence)
	if err != nil {
		return shim.Error(err.Error())
	}
	err = stub.PutState(args[1], eviJSONasBytes)
	if err != nil {
		return shim.Error(err.Error())
	}
	return shim.Success(nil)
}
//正向保理查询
func (t *MAChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	res := checkParams(args, 2, 2)
	if res != "" {
		return shim.Error(res)
	}
	var obj Obj
	err := json.Unmarshal([]byte(args[0]), &obj)
	if err != nil {
		return shim.Error(err.Error())
	}
	evidences, err := stub.GetState(args[1])
	if err != nil {
		return shim.Error("Failed to get evidence: " + err.Error())
	} else if evidences == nil {
		fmt.Println("This evidence not exists")
		return shim.Error("This evidence not exists")
	}
	return shim.Success(evidences)
}
func (t *MAChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	fmt.Println("开始删除")
	res := checkParams(args, 2, 2)
	if res != "" {
		return shim.Error(res)
	}
	var obj Obj
	err := json.Unmarshal([]byte(args[0]), &obj)
	if err != nil {
		return shim.Error(err.Error())
	}
	key := args[1]
	evidences, err := stub.GetState(key)
	fmt.Println("删除查询到的数据"+string(evidences))
	if err != nil {
		return shim.Error("Failed to get evidence: " + err.Error())
	} else if evidences == nil {
		fmt.Println("This evidence not exists")
		return shim.Error("This evidence not exists")
	}
	err = stub.DelState(key)
	if err != nil {
		return shim.Error("Failed to delete state")
	}
	return shim.Success(nil)
}
//星券实例化上链
func (t *MAChaincode) initAgreement(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	res := checkParams(args, 30, 30)
	if res != "" {
		return shim.Error(res)
	}
	var obj Obj
	err := json.Unmarshal([]byte(args[0]), &obj)
	if err != nil {
		return shim.Error(err.Error())
	}
	//-------------------
	h := sha256.New()
	h.Write([]byte(args[0]+args[1]+args[2]+args[3]+args[4]+args[5]+args[6]+args[7]+args[8]+args[9]+args[10]+args[11]+args[12]+args[13]+args[14]+args[15]+args[16]+args[17]+args[18]+args[19]+args[20]+args[21]+args[22]+args[23]+args[24]+args[25]+args[26]+args[27]+args[28]+args[29]))
	sum := h.Sum(nil)
	maxchainHash := hex.EncodeToString(sum)
	StarContract := &StarContract{args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28],args[29],obj.Files,maxchainHash}
	evidenceXQ := &EvidenceXQ{AppId: obj.AppId, SystemId: obj.SystemId,ContractNum:args[1]}
	evidenceXQ.StarContract = *StarContract
	//-----------------
	evidences, err := stub.GetState(args[1])
	if err != nil {
		return shim.Error("Failed to get evidence: " + err.Error())
	} else if evidences != nil {
		fmt.Println("This evidence already exists")
		return shim.Error("This evidence already exists")
	}

	eviJSONasBytes, err := json.Marshal(evidenceXQ)
	if err != nil {
		return shim.Error(err.Error())
	}
	fmt.Println("key"+evidenceXQ.ContractNum)
	err = stub.PutState(args[1], eviJSONasBytes)
	if err != nil {
		return shim.Error(err.Error())
	}
	return shim.Success(nil)
}
//星券更新
func (t *MAChaincode) agreementUpdate(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	res := checkParams(args, 30, 30)
	if res != "" {
		return shim.Error(res)
	}
	var obj Obj
	err := json.Unmarshal([]byte(args[0]), &obj)
	if err != nil {
		return shim.Error(err.Error())
	}
	h := sha256.New()
	h.Write([]byte(args[0]+args[1]+args[2]+args[3]+args[4]+args[5]+args[6]+args[7]+args[8]+args[9]+args[10]+args[11]+args[12]+args[13]+args[14]+args[15]+args[16]+args[17]+args[18]+args[19]+args[20]+args[21]+args[22]+args[23]+args[24]+args[25]+args[26]+args[27]+args[28]+args[29]))
	sum := h.Sum(nil)
	maxchainHash := hex.EncodeToString(sum)
	StarContract := &StarContract{args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28],args[29],obj.Files,maxchainHash}
	evidenceXQ := &EvidenceXQ{AppId: obj.AppId, SystemId: obj.SystemId,ContractNum:args[1]}
	fmt.Println("--------evidenceData-----")
	fmt.Println(evidenceXQ)
	evidenceXQ.StarContract = *StarContract
	//-----------------
	evidences, err := stub.GetState(args[1])
	if err != nil {
		return shim.Error("Failed to get evidence: " + err.Error())
	} else if evidences == nil {
		fmt.Println("This evidence not exists")
		return shim.Error("This evidence not exists")
	}
	eviJSONasBytes, err := json.Marshal(evidenceXQ)
	if err != nil {
		return shim.Error(err.Error())
	}
	err = stub.PutState(args[1], eviJSONasBytes)
	if err != nil {
		return shim.Error(err.Error())
	}
	return shim.Success(nil)
}
//星券查询
func (t *MAChaincode) queryAgreement(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	res := checkParams(args, 2, 2)
	if res != "" {
		return shim.Error(res)
	}
	var obj Obj
	err := json.Unmarshal([]byte(args[0]), &obj)
	if err != nil {
		return shim.Error(err.Error())
	}
	evidences, err := stub.GetState(args[1])
	if err != nil {
		return shim.Error("Failed to get evidence: " + err.Error())
	} else if evidences == nil {
		fmt.Println("This evidence not exists")
		return shim.Error("This evidence not exists")
	}
	return shim.Success(evidences)
}

func main() {
	err := shim.Start(new(MAChaincode))
	if err != nil {
		fmt.Printf("Error starting New key per invoke: %s", err)
	}
}
